package com.example;

import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * Todo 日期、时间工具类
 *
 * @Author jiangtao
 * @CreateBy 2019-07-05 6:03 PM
 * @UpdateBy jiangtao
 * @Version v1.0
 */
public class DateUtil {

    public static final String YEAR = "yyyy";
    public static final String MONTH = "MM";
    public static final String YEAR_MONTH = "yyyy-MM";
    public static final String DATE = "yyyy-MM-dd";
    public static final String TIME = "HH:mm:ss";
    public static final String HOUR_MINUTE = "HH:mm";
    public static final String DATETIME = "yyyy-MM-dd HH:mm:ss";
    public static final String DATETIME_1 = "yyyyMMddHHmmss";
    public static final String DATETIME2 = "yyyy-MM-dd HH:mm";

    private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATETIME);
    private static DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");


    /**
     * 时间戳
     *
     * @return
     */
    public static long time() {
        return LocalDateTime.now().toInstant(ZoneOffset.of("UTC+08:00")).toEpochMilli();
    }

    /**
     * LocalDateTime 格式化 yyyy-MM-dd HH:mm:ss
     *
     * @param formatter
     * @return
     */
    public static DateTimeFormatter formatter(String formatter) {
        return DateTimeFormatter.ofPattern(formatter);
    }

    /**
     * Date 格式化
     *
     * @param format 格式
     * @return SimpleDateFormat
     */
    public static SimpleDateFormat format(String format) {
        return new SimpleDateFormat(format);
    }

    /**
     * 默认时区 UTC+08:00
     *
     * @return
     */
    public static ZoneId zoneId() {
        return ZoneId.of("UTC+08:00");
    }


    /**
     * 当前时间
     *
     * @return String
     */
    public static String now() {
        return LocalDateTime.now().format(formatter);
    }

    /**
     * 格式化当前时间
     *
     * @param format 格式
     * @return String
     */
    public static String now(String format) {
        if (StringUtils.isEmpty(format)) {
            return now();
        }
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(format);
        return LocalDateTime.now().format(fmt);
    }

    public static String fmtDate(String format) {
        return now(format);
    }

    /**
     * Date 转 String
     *
     * @param date 日期
     * @return String
     */
    public static String date2Str(Date date) {
        if (date == null) {
            return now();
        }
        return localDateTime2Str(date2LocalDateTime(date));
    }

    /**
     * Date 转 String
     *
     * @param date      日期
     * @param formatter 格式
     * @return
     */
    public static String date2Str(Date date, String formatter) {
        if (date == null) {
            return now();
        }
        return localDateTime2Str(date2LocalDateTime(date), formatter);
    }

    /**
     * LocalDate 转 String
     *
     * @param date 日期
     * @return String
     */
    public static String localDate2Str(LocalDate date) {
        return localDate2Str(date, formatter2);
    }

    /**
     * LocalDate 转 String
     *
     * @param date      日期
     * @param formatter 格式
     * @return String
     */
    public static String localDate2Str(LocalDate date, DateTimeFormatter formatter) {
        if (date == null) {
            return LocalDate.now().format(formatter2);
        }
        return date.format(formatter2);
    }

    /**
     * LocalDateTime 转 String
     *
     * @param date LocalDateTime
     * @return String
     */
    public static String localDateTime2Str(LocalDateTime date) {
        if (date == null) {
            return now();
        } else {
            return date.format(formatter);
        }
    }

    /**
     * LocalDateTime 转 String
     *
     * @param date      日期
     * @param formatter 格式
     * @return String
     */
    public static String localDateTime2Str(LocalDateTime date, String formatter) {
        if (date == null) {
            return now();
        } else {
            return date.format(formatter(formatter));
        }
    }


    /**
     * new Date()
     *
     * @return Date
     */
    public static Date date() {
        return new Date();
    }

    /**
     * String 转 Date
     *
     * @param date 字符串
     * @return Date
     */
    public static Date str2Date(String date) {
        LocalDateTime ldt = str2LocalDateTime(date);
        return localDateTime2Date(ldt);
    }

    /**
     * String 转 Date
     *
     * @param date      字符串
     * @param formatter 格式
     * @return Date
     */
    public static Date str2Date(String date, String formatter) {
        LocalDateTime ldt = str2LocalDateTime(date, formatter);
        return localDateTime2Date(ldt);
    }

    /**
     * LocalDate 转 Date
     *
     * @param ld LocalDate
     * @return Date
     */
    public static Date localDate2Date(LocalDate ld) {
        if (ld == null) {
            return new Date();
        }
        return Date.from(ld.atStartOfDay().atZone(zoneId()).toInstant());
    }

    /**
     * LocalDateTime 转 Date
     *
     * @param ldt LocalDateTime
     * @return Date
     */
    public static Date localDateTime2Date(LocalDateTime ldt) {
        if (ldt == null) {
            return new Date();
        }
        return Date.from(ldt.atZone(zoneId()).toInstant());
    }


    /**
     * LocalDate 转 Date
     *
     * @param date
     * @return LocalDate
     */
    public static LocalDate str2LocalDate(String date) {
        return str2LocalDateTime(date).toLocalDate();
    }

    /**
     * LocalDate 转 Date
     *
     * @param date      日期
     * @param formatter 格式
     * @return LocalDate
     */
    public static LocalDate str2LocalDate(String date, String formatter) {
        //return str2LocalDateTime(date, formatter).toLocalDate();
        if (date == null) {
            return LocalDate.now();
        } else {
            return LocalDate.parse(date, formatter(formatter));
        }
    }

    /**
     * LocalDate 转 Date
     *
     * @param date 日期
     * @return LocalDate
     */
    public static LocalDate date2LocalDate(Date date) {
        if (date == null) {
            return LocalDate.now();
        }
        return date.toInstant().atZone(zoneId()).toLocalDate();
    }


    /**
     * String 转 LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime str2LocalDateTime(String date) {
        if (date == null) {
            return LocalDateTime.now();
        } else {
            return LocalDateTime.parse(date, formatter);
        }
    }

    /**
     * String 转 LocalDateTime 自定义格式
     *
     * @param date
     * @param formatter
     * @return
     */
    public static LocalDateTime str2LocalDateTime(String date, String formatter) {
        if (date == null) {
            return LocalDateTime.now();
        } else {
            return LocalDateTime.parse(date, formatter(formatter));
        }
    }

    /**
     * Date 转 LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime date2LocalDateTime(Date date) {
        if (date == null) {
            return LocalDateTime.now();
        }
        return date.toInstant().atZone(zoneId()).toLocalDateTime();
    }


    /*
     * 获取指定日期的年份
     * @param d
     * @retrun
     * */
    public static int getYear(Date d) {
        Calendar cal = Calendar.getInstance(TimeZone.getDefault());
        cal.setTime(d);
        return cal.get(Calendar.YEAR);
    }

    /*
     * 获取指定日期的月份
     * @param d
     * @retrun
     * */
    public static int getMonth(Date d) {
        Calendar cal = Calendar.getInstance(TimeZone.getDefault());
        cal.setTime(d);
        return cal.get(Calendar.MONTH);
    }

    /**
     * 计算两个日期间隔多少天
     *
     * @param before
     * @param after
     * @return
     */
    public static int getDiffDays(LocalDateTime before, LocalDateTime after) {
        if (before == null || after == null) {
            return 0;
        }
        if (before.isBefore(after)) {
            return after.getDayOfYear() - before.getDayOfYear();
        } else {
            return before.getDayOfYear() - after.getDayOfYear();
        }
    }

    public static int getDiffDays(LocalDate before, LocalDate after) {
        if (before == null || after == null) {
            return 0;
        }
        if (before.isBefore(after)) {
            return after.getDayOfYear() - before.getDayOfYear();
        } else {
            return before.getDayOfYear() - after.getDayOfYear();
        }
    }

    public static int getDiffDays(Date before, Date after) {
        if (null == before || after == null) {
            return 0;
        }
        return getDiffDays(date2LocalDateTime(before), date2LocalDateTime(after));
    }

    public static int getDiffDays(String before, String after) {
        if (StringUtils.isBlank(before) || StringUtils.isBlank(after)) {
            return 0;
        }
        return getDiffDays(str2LocalDateTime(before), str2LocalDateTime(after));
    }

    public static int getDiffDays(long before, long after) {
        return getDiffDays(date2LocalDateTime(new Date(before)), date2LocalDateTime(new Date(after)));
    }


    /**
     * 美化时间【刚刚、几秒前、几个月前】
     * 默认时间格式 yyyy-MM-dd HH:mm:ss
     *
     * @param date 时间
     * @return 美化后的时间
     */
    public static String prettify(LocalDateTime date) {
        if (null == date) {
            return prettify(time());
        } else {
            return prettify(date.toInstant(ZoneOffset.of("+8")).toEpochMilli());
        }
    }

    public static String prettify(Date date) {
        if (null == date) {
            return prettify(time());
        } else {
            return prettify(date.getTime());
        }
    }

    public static String prettify(String date) {
        if (StringUtils.isBlank(date)) {
            return prettify(time());
        } else {
            return prettify(str2Date(date).getTime());
        }
    }

    public static String prettify(String date, String formatter) {
        if (StringUtils.isBlank(date)) {
            return prettify(time());
        } else {
            return prettify(str2Date(date, formatter).getTime());
        }
    }

    private static String prettify(long time) {
        String str;
        if (10 == ("" + time).length()) {
            time = time * 1000;
        }
        long diff = (Calendar.getInstance().getTimeInMillis() - time) / 1000;
        if (365 * 24 * 60 * 60 < diff) {
            // str = (int) (diff / (365 * 24 * 60 * 60)) + "年前";
            // str = format("yyyy-MM-dd HH:mm").format(new Date(time));
            str = format("yyyy年MM月dd日 HH:mm").format(new Date(time));
        } else if (180 * 24 * 60 * 60 < diff) {
            // str = (int) (diff / (180 * 24 * 60 * 60)) + "个月前";
            str = "半年前";
        } else if (30 * 24 * 60 * 60 < diff) {
            str = (int) (diff / (30 * 24 * 60 * 60)) + "个月前";
        } else if (7 * 24 * 60 * 60 < diff) {
            str = (int) (diff / (7 * 24 * 60 * 60)) + "周前";
        } else if (24 * 60 * 60 < diff) {
            str = (int) (diff / (24 * 60 * 60)) + "天前";
        } else if (60 * 60 < diff) {
            str = (int) (diff / (60 * 60)) + "小时前";
        } else if (30 * 60 < diff) {
            str = "半小时前";
        } else if (60 < diff) {
            str = (int) (diff / (60)) + "分前";
        } else if (15 < diff) {
            str = diff + "秒前";
        } else {
            str = "刚刚";
        }
        return str;
    }

    /**
     * 获得当前日期是本周的第几天
     *
     * @param localDate 日期
     * @return 日期是本周的第几天
     */
    public static int getDayOfWeek(LocalDate localDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtil.localDate2Date(localDate));
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek == 1) {
            return 7;
        } else {
            return dayOfWeek - 1;
        }
    }

    public static void main(String[] args) {
        // 获取秒
        // System.out.println(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")));
        // 获取毫秒
        // System.out.println(System.currentTimeMillis());
        // System.out.println(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli());

        /*System.out.println(prettify("2018-01-12 12:30:56"));
        System.out.println(prettify("2019-10-09 12:30:56"));
        System.out.println(prettify("2020-01-12 12:30:56"));
        System.out.println(prettify("2020-05-12 12:30:56"));
        System.out.println(prettify("2020-08-12 12:30:56"));
        System.out.println(prettify("2020-09-18 12:30:56"));
        System.out.println(prettify("2020-10-01 12:30:56"));
        System.out.println(prettify("2020-10-07 12:30:56"));
        System.out.println(prettify("2020-10-08 23:30:56"));
        System.out.println(prettify("2020-10-09 06:30:56"));
        System.out.println(prettify("2020-10-09 12:30:56"));
        System.out.println(prettify("2020-10-09 15:00:56"));
        System.out.println(prettify("2020-10-09 15:30:56"));
        System.out.println(prettify("2020-10-09 15:50:56"));
        System.out.println(prettify("2020-10-09 15:59:30"));
        System.out.println(prettify("2020-10-09 16:01:30"));
        System.out.println(prettify(time() - 20000));
        System.out.println(prettify(time() - 5000));*/
        //System.out.println(getDiffDays("2020-01-02 12:20:20", "2020-01-02 12:20:20"));

//        LocalDate with = LocalDate.now().with(DayOfWeek.MONDAY);
//        System.out.println(with);

//        System.out.println(LocalDate.now().with(DayOfWeek.MONDAY));

        LocalDate localDate = LocalDate.of(2020, 11, 20);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtil.localDate2Date(localDate));
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek == 1) {
            dayOfWeek = 7;
        } else {
            dayOfWeek = dayOfWeek - 1;
        }
        System.out.println(dayOfWeek);
    }
}
